# -*- coding: utf-8 -*-
# @Time    : 2024/7/26 16:30
# @Author  : yujiahao
# @File    : 64_fastapi_unicornmiddleware.py
# @description: 高级中间件


"""
添加 ASGI 中间件：

1. 因为 FastAPI 基于 Starlette，且执行 ASGI 规范，所以可以使用任意 ASGI 中间件。

2. 中间件不必是专为 FastAPI 或 Starlette 定制的，只要遵循 ASGI 规范即可。

3. 总之，ASGI 中间件是类，并把 ASGI 应用作为第一个参数。

4. 因此，有些第三方 ASGI 中间件的文档推荐以如下方式使用中间件：
    from unicorn import UnicornMiddleware

    app = SomeASGIApp()

    new_app = UnicornMiddleware(app, some_config="rainbow")

5. 但 FastAPI（实际上是 Starlette）提供了一种更简单的方式，能让内部中间件在处理服务器错误的同时，还能让自定义异常处理器正常运作。

6. 为此，要使用 app.add_middleware() （与 CORS 中的示例一样）：
    from fastapi import FastAPI
    from unicorn import UnicornMiddleware

    app = FastAPI()

    app.add_middleware(UnicornMiddleware, some_config="rainbow")

7. app.add_middleware() 的第一个参数是中间件的类，其它参数则是要传递给中间件的参数。
"""
from starlette.middleware.gzip import GZipMiddleware
from starlette.middleware.trustedhost import TrustedHostMiddleware

# todo 集成中间件

"""
以下几个示例中也可以使用 from starlette.middleware.something import SomethingMiddleware。

FastAPI 在 fastapi.middleware 中提供的中间件只是为了方便开发者使用，但绝大多数可用的中间件都直接继承自 Starlette。
"""

from fastapi import FastAPI
from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware
from fastapi.middleware.gzip import GZipMiddleware

app = FastAPI()

# todo TrustedHostMiddleware
# 强制所有传入请求都必须正确设置 Host 请求头，以防 HTTP 主机头攻击。
"""
1. 支持以下参数：

    1.1 allowed_hosts - 允许的域名（主机名）列表。
        - 你可以使用通配符域名（如 *.example.com）来匹配子域名。
        - 使用 allowed_hosts=["*"] 可以允许任意主机名。
        - 如果省略该参数，则中间件不会进行主机名验证。

    1.2 如果传入的请求没有通过验证，则发送 400 响应。
"""
app.add_middleware(
    TrustedHostMiddleware, allowed_hosts=["localhost", "127.0.0.1", "[::1]"]
)


@app.get("/hh")
async def main_hh():
    return {"message": "Hello World"}


# todo HTTPSRedirectMiddleware


"""
1. add_middleware 方法
    add_middleware 是 FastAPI 应用实例 (FastAPI 类) 的一个方法，用于向应用添加中间件。
    中间件是一个在请求被处理之前和响应被发送之前执行的函数，通常用于处理跨多个路由的通用功能，
    例如日志记录、用户认证、CORS（跨域资源共享）等。

2. HTTPSRedirectMiddleware
    HTTPSRedirectMiddleware 是 FastAPI 提供的一个中间件，用于将所有的 HTTP 请求重定向到 HTTPS。
    这有助于确保所有的通信都是加密的，从而提高应用的安全性。

3. 工作原理
    当你添加 HTTPSRedirectMiddleware 到你的 FastAPI 应用时，以下是它的工作原理：

    3.1 拦截请求：每个进入 FastAPI 应用的请求都会首先经过这个中间件。

    3.2 检查协议：中间件检查请求的协议（HTTP 或 HTTPS）。

    3.3 重定向请求：如果请求是通过 HTTP 发送的，中间件会返回一个重定向响应，
        指示客户端（例如浏览器）重新发起一个 HTTPS 请求。
"""
# app.add_middleware(HTTPSRedirectMiddleware)


# @app.get("/")
# async def main():
#     """
#     运行的时候会报错，ERR_SSL_PROTOCOL_ERROR 此网站无法提供安全连接
#     因为HTTPSRedirectMiddleware 强制所有传入请求必须是 https 或 wss。
#     任何传向 http 或 ws 的请求都会被重定向至安全方案。
#
#     1. 为什么会导致 ERR_SSL_PROTOCOL_ERROR
#         在本地开发环境中，通常不会配置 HTTPS（即没有 SSL 证书）。
#         当你添加了 HTTPSRedirectMiddleware 后，它会将所有 HTTP 请求重定向到 HTTPS。
#         如果你的本地服务器没有配置 HTTPS，那么浏览器在尝试通过 HTTPS 访问时，
#         就会出现 ERR_SSL_PROTOCOL_ERROR 错误，因为服务器无法提供有效的 SSL 证书。
#     """
#
#     return {"message": "Hello World"}


# todo GZipMiddleware

# 处理 Accept-Encoding 请求头中包含 gzip 请求的 GZip 响应。
# 中间件会处理标准响应与流响应。
# 支持以下参数：
# minimum_size - 小于最小字节的响应不使用 GZip。 默认值是 500。
app.add_middleware(GZipMiddleware, minimum_size=1000)


@app.get("/aa")
async def main_aa():
    return "somebigcontent"
